﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LeeAnn.Framework;
namespace LeeAnn
{
    public abstract class AnnFramework
    {
        public List<Neuron> InputOutputNeurons = new List<Neuron>();
        public List<int> Inputs = new List<int>();
        public List<int> Outputs = new List<int>();
        public List<Neuron> Neurons = new List<Neuron>();
        public Neuron GetInputNeuron(int n)
        {
            if (n >= Inputs.Count)
                return new Neuron();
            else
                return InputOutputNeurons[Inputs[n]];
        }
        public Neuron GetOutputNeuron(int n)
        {
            if (n >= Outputs.Count)
                return new Neuron();
            else
                return InputOutputNeurons[Outputs[n]];
        }
        public abstract void DesignNetwork();
        public abstract void Update();

        public void addInputNeuron(NeuronPlaceholder OutputToNeuron,LeeAnn.Neuron.CalculateIODelegate CalculateFunction)
        {
            //Create the InputNeuron
            Neuron InputNeuron = new Neuron();
            //Add the CalculateFunction
            InputNeuron.CalculateEvent += CalculateFunction;
            //Add the OutputToNeuron to the InputNeuron
            InputNeuron.Outputs.Add(OutputToNeuron);
            //Add the index of the InputNeuron to the list
            Inputs.Add(InputOutputNeurons.Count);
            //Add the Neuron to the list
            InputOutputNeurons.Add(InputNeuron);
        }
        public void addInputNeuron(ArrayList OutputToNeuron, LeeAnn.Neuron.CalculateIODelegate CalculateFunction)
        {
            //Create the InputNeuron
            Neuron InputNeuron = new Neuron();
            //Add the CalculateFunction
            InputNeuron.CalculateEvent += CalculateFunction;
            foreach (NeuronPlaceholder np in OutputToNeuron)
            {
                //Add the OutputToNeuron to the InputNeuron
                InputNeuron.Outputs.Add(np);
            }
            //Add the index of the InputNeuron to the list
            Inputs.Add(InputOutputNeurons.Count);
            //Add the Neuron to the list
            InputOutputNeurons.Add(InputNeuron);
        }
        public void addOutputNeuron( NeuronPlaceholder InputFromNeuron,LeeAnn.Neuron.CalculateIODelegate CalculateFunction)
        {
            //Create the Output Neuron
            Neuron OutputNeuron = new Neuron();
            //Add the CalculateFunction
            OutputNeuron.CalculateEvent += CalculateFunction;
            //Main index for OutputNeuron
            int index = InputOutputNeurons.Count;
            //Set the position of the output neuron, basically an index here.
            OutputNeuron.Position = new Position3D(index, 0, 0);
            //Adds the index of the OutputNeuron to the Outputs array
            Outputs.Add(index);
            //Create a FeedForwardNeuronPlaceholder
            LeeAnn.FeedForward.FeedForwardNeuronPlaceholder ffnn = new LeeAnn.FeedForward.FeedForwardNeuronPlaceholder(OutputNeuron.Position);
            ffnn.nType = NeuronPlaceholder.NeuronType.Output;

            //Gets the neuron that we want to get output from.
            int i = InputFromNeuron.getNeuron(this);
            //Add the FeedForwardNeuronPlaceholder we made for the OutputNeuron to the output of the Input Neuron(lol)
            Neurons[i].AddOutput(ffnn);
            //Finally, add the OutputNeuron to the InputOutputNeurons
            InputOutputNeurons.Add(OutputNeuron);
        }
        public void addOutputNeuron(ArrayList InputFromNeuron, LeeAnn.Neuron.CalculateIODelegate CalculateFunction)
        {

            //Create the Output Neuron
            Neuron OutputNeuron = new Neuron();
            //Add the CalculateFunction
            OutputNeuron.CalculateEvent += CalculateFunction;
            //Main index for OutputNeuron
            int index = InputOutputNeurons.Count;
            //Set the position of the output neuron, basically an index here.
            OutputNeuron.Position = new Position3D(index, 0, 0);
            //Adds the index of the OutputNeuron to the Outputs array
            Outputs.Add(index);
            //Create a FeedForwardNeuronPlaceholder
            LeeAnn.FeedForward.FeedForwardNeuronPlaceholder ffnn = new LeeAnn.FeedForward.FeedForwardNeuronPlaceholder(OutputNeuron.Position);
            ffnn.nType = NeuronPlaceholder.NeuronType.Output;
            foreach (NeuronPlaceholder np in InputFromNeuron)
            {

                //Gets the neuron that we want to get output from.
                int i = np.getNeuron(this);
                //Add the FeedForwardNeuronPlaceholder we made for the OutputNeuron to the output of the Input Neuron(lol)
                Neurons[i].AddOutput(ffnn);
            }
            //Finally, add the OutputNeuron to the InputOutputNeurons
            InputOutputNeurons.Add(OutputNeuron);
        }
    }
}
